/*lobby.c*/
#include "cineplex.h"

struct Message Lobby_GetMessage(int name)
{
	agentsStarted = agentsStarted + 1;
	/*this will be the null output*/
	lobby.tempMsg.name = NullMsg;
	lobby.tempMsg.sender = NullMsg;
	
	Acquire(loopLock);
	for(i = 0; i < lobby.numMsgs; i++)
	{
		if(lobby.msgList[i].name == name)
		{
			lobby.tempMsg.name = name;
			lobby.tempMsg.sender = lobby.msgList[i].sender;
			lobby.numMsgs = lobby.numMsgs - 1;
			break;
		}
	}
	for(k = i; k < 2; k++)
	{
		/*movin on up*/
		lobby.msgList[k].name = lobby.msgList[k+1].name;
		lobby.msgList[k].sender = lobby.msgList[k+1].sender;
	}
	lobby.msgList[2].name = NullMsg;
	lobby.msgList[2].sender = NullMsg;
	Release(loopLock);
		
	return lobby.tempMsg;
}

void Lobby_Scheduler()
{
	Wait(initCond, initLock);
	lobby.runScheduler = runSchedulers;
	do
	{
		/*printf("%s running Scheduler...\n",myName);*/
		if(lobby.state == IDLING)
		{
			Lobby_IdleAction();
		}else if(lobby.state == STARTRELEASING)
		{
			Lobby_StartReleasing();
		}else if(lobby.state == ASKCOUNT)
		{
			Lobby_AskCount();
		}else if(lobby.state == WAITCOUNT)
		{
			Lobby_WaitCount();
		}else if(lobby.state == WAITFORTECH)
		{
			Lobby_WaitForTech();
		}
	} while(lobby.runScheduler);
}

void Lobby_IdleAction()
{
	Acquire(lobby.msgLock);
	/*IterList* custMsg = msgList->Find("IAmInLobby");*/
	Lobby_GetMessage(IAmInLobby);
	if(lobby.tempMsg.sender != NullMsg)
	{	
		/*printf("Adding customer to lobby\n");*/
		ConsoleAcquire();
			Write("Adding customer to lobby\n", 25, ConsoleOutput);
		ConsoleRelease();
		/*custInLobby->Append(custMsg->Get(0));*/
		lobby.custInLobby[lobby.numInLobby] = lobby.tempMsg.sender;
		lobby.numInLobby = lobby.numInLobby + 1;
		Release(lobby.msgLock);
	}else{
		/*IterList* manMsg = msgList->Find("NewMovieStarting");*/
		Lobby_GetMessage(NewMovieStarting);
		if(!lobby.tempMsg.sender == NullMsg)
		{
			lobby.state = STARTRELEASING;
			Release(lobby.msgLock);
		}else{
			Release(lobby.msgLock);
			Lobby_WaitForTech(); /*since state isn't set to wait, this will answer the msg if sent, sleep normally otherwise*/
			/*sleepCon->Wait(msgLock);*/
		}
	}
}

void Lobby_StartReleasing()
{
	/*custInLobby->AppendMeTo(custToAsk);*/
	Acquire(loopLock);
	for(i = 0; i < MAX_CUSTOMERS/MAX_GROUP_SIZE + 1; i++)
	{
		lobby.custToAsk[i] = lobby.custInLobby[i];
	}
	Release(loopLock);
	lobby.repliesWaiting = lobby.numInLobby;
	lobby.msgsToSend = lobby.numInLobby;
	/*printf("Releasing lobby - %d groups\n", custToAsk->getSize());*/
	lobby.state = ASKCOUNT;
	/*lobby.repliesWaiting = custToAsk->getSize();*/
}

void Lobby_AskCount()
{
	if(lobby.msgsToSend == 0) lobby.state = WAITCOUNT;
	else
	{	
		/*custInLobby->Pop(0);*/
		lobby.numInLobby = lobby.numInLobby - 1;
		lobby.replyTo = lobby.custToAsk[lobby.numInLobby];
		/*printf("%s requesting size from %s\n",myName,((Customer*)replyTo)->myName);*/
		/*((Customer*)replyTo)->SendMessage("HowManyInYourGroup",1,this);*/
		SendMessage(T_CUSTOMER, lobby.replyTo, HowManyInYourGroup, 0);
	}
}

void Lobby_WaitCount()
{
	if(lobby.repliesWaiting == 0)
	{
		lobby.state = WAITFORTECH;
		return;
	}
	Acquire(lobby.msgLock);
	/*IterList* custMsg = msgList->Find("WeAreLegion");*/
	Lobby_GetMessage(WeAreLegion);
	if(!lobby.tempMsg.sender == NullMsg)
	{
		Release(lobby.msgLock);
		lobby.replyTo = lobby.tempMsg.sender;
		/*msgInt = custMsg->GetInt(1);*/
		/*printf("%s acquiring seating lock\n", myName);*/
		Acquire(seatingLock);
		/*printf("%s acquired seating lock\n", myName);*/
		lobby.repliesWaiting = lobby.repliesWaiting - 1;
		if(totalSeats - seatsFilled > groupSizes[customers[lobby.replyTo].groupNumber])
		{
			/*((Customer*)replyTo)->SendMessage("LeaveLobby",0);*/
			SendMessage(T_CUSTOMER, lobby.replyTo, LeaveLobby, 0);
			/*printf("%s Releasing %s with size %d\n",myName,((Customer*)replyTo)->myName, msgInt);*/
			Release(seatingLock);
		}else
		{
			/*printf("%s NOT Releasing %s with size %d\n",myName,((Customer*)replyTo)->myName, msgInt);*/
			/*custInLobby->Append((Customer*)replyTo);*/
			lobby.custInLobby[lobby.numInLobby] = lobby.replyTo;
			Release(seatingLock);
		}
	}else{
		Wait(lobby.sleepCon, lobby.msgLock);
	}
}

void Lobby_WaitForTech()
{
	Acquire(lobby.msgLock);
	/*IterList* techMsg = msgList->Find("AreYouIdle");*/
	Lobby_GetMessage(AreYouIdle);
	if(lobby.tempMsg.sender != NullMsg)
	{
		Release(lobby.msgLock);
		lobby.replyTo = lobby.tempMsg.sender;
		/*printf("%s telling %s lobby is done\n",myName,((MovieTech*)replyTo)->myName);*/
		/*((MovieTech*)replyTo)->SendMessage("LobbyEmpty",0);*/
		SendMessage(T_MOVIETECH, lobby.replyTo, LobbyEmpty, 0);
		lobby.state = IDLING;
	}else{
		/*printf("~~~lobby sleeping~~~\n");*/
		Wait(lobby.sleepCon, lobby.msgLock);
		/*printf("~~~lobby waking~~~\n");*/
	}
}
